package cn.jiahua.hospital.controller;

import ch.qos.logback.core.net.SyslogOutputStream;
import cn.jiahua.hospital.constants.Constants;
import cn.jiahua.hospital.dto.Result;
import cn.jiahua.hospital.pojo.Doctor;
import cn.jiahua.hospital.pojo.HdidRelation;
import cn.jiahua.hospital.pojo.Hospital;
import cn.jiahua.hospital.pojo.User;
import cn.jiahua.hospital.service.*;
import cn.jiahua.hospital.service.impl.EstSQLException;
import cn.jiahua.hospital.utils.RedisUtil;
import cn.jiahua.hospital.utils.ResultUtils;
import cn.jiahua.hospital.vo.TokenVo;
import com.aliyun.dysmsapi20170525.models.SendSmsResponseBody;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.StringRedisSerializer;
import org.springframework.http.HttpRequest;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.xml.crypto.Data;
import java.net.SocketTimeoutException;
import java.util.*;

/**
 * @author wjz
 * @date 2021/4/20 - 9:57
 */

@RestController
@Api(tags = "登录")
@RequestMapping("/api/")
public class LoginController {
    @Autowired
    RedisUtil redisUtil;

    @Autowired
    SmsLogService smsLogService;

    @Autowired
    UserService userService;

    @Autowired
    TokenService tokenService;

    @Autowired
    HospitalService HospitalService;

    @Autowired
    DoctorService doctorService;

    @Autowired
    HdidRelationService hdidRelationService;

    @Autowired
    RedisTemplate redisTemplate;


    @ApiOperation(value = "查询redis里面的所有token数据", produces = "application/json", notes = "发送短信")
    @GetMapping("/redis/")
        public Set getRedis(){
            //获取所有key
        Set<String> keys =redisTemplate.keys("token"+"*");
       /* //创建集合
        HashMap<Object,Object> map=new HashMap<>();
        //循环
        for(String key:keys){
            //获取Key对应的value值
            redisTemplate.setValueSerializer(new StringRedisSerializer());
            Object Value=redisTemplate.opsForValue().get(key);
            map.put(key,Value);
            System.out.println(key);
        }*/
        //返回集合
        return keys;
        }



    @ApiOperation(value = "发送短信验证码接口", produces = "application/json", notes = "发送短信")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "phone", value = "手机号码", required = true, dataType = "string"),
            @ApiImplicitParam(name = "codeType", value = "验证码类型，0登录 1注册 2绑定手机号码 ", required = true, dataType = "string")
    })
    @PostMapping("/sms/verfycode")
    public Result verifyCode(String phone, Integer codeType) {
        //1.判断手机号码是否正确
        if (!checkPhone(phone)) {
            return ResultUtils.returnFail("手机号码错误", "200001");
        }
        //2。判断短信验证码是否正确
        if (!checkCodeType(codeType.toString())) {
            return ResultUtils.returnFail("请求异常", "200002");
        }

        //3.验证码发送的频率
        if (!checksmsCode(phone, codeType)) {
            return ResultUtils.returnFail("太频繁发送短信验证了", "200003");
        }

        //4.发送短信
        try {
            SendSmsResponseBody Code = smsLogService.sendMessage(phone, codeType);

            if (!Code.getCode().equals("OK")) {
                return ResultUtils.returnFail(Code.getMessage());
            }
        } catch (Exception e) {
            return ResultUtils.returnFail("发送短信系统异常");
        }

        return ResultUtils.returnSuccess();
    }
    @ApiOperation(value = "手机验证码注册接口", produces = "application/json", notes = "使用手机验证码进行注册、登录接口")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "phone", value = "手机号码", required = true, dataType = "string"),
            /*    @ApiImplicitParam(name = "sms", value = "验证码", required = true, dataType = "string"),*/
    })
    @PostMapping("/user/binding/login/sms")
    public Result bindingLogin(@RequestParam("phone") String phone, /*@RequestParam("sms") String sms,*/
                                HttpServletResponse response) {
    /*    //1.验证手机号码是否正确
        if (!checkPhone(phone)) {
            return ResultUtils.returnFail("手机号码错误，请重新输入", "200001");
        }

        //2.校验验证码是否存在在redis中
        String key = Constants.Redis.PREFIX_SMS + "2" + ":" + phone;
        String keyvalue = (String) redisUtil.get(key);
        if (keyvalue == null || !keyvalue.equals(sms)) {
            return ResultUtils.returnFail("验证码有误，请重新输入", "200004");
        }*/
        Map<String, Object> map = new HashMap<String, Object>();
        map.put("userPhone",phone);
        List<User> listUser = userService.getUserListByMap(map);
        if (listUser != null && listUser.size()>0) {
            return ResultUtils.returnFail("该手机已被绑定");
        }
        return ResultUtils.returnSuccess("验证码和手机号码正确");
    }

    @ApiOperation(value = "手机验证码注册接口", produces = "application/json", notes = "使用手机验证码进行注册、登录接口")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "phone", value = "手机号码", required = true, dataType = "string"),
        /*    @ApiImplicitParam(name = "sms", value = "验证码", required = true, dataType = "string"),*/
            @ApiImplicitParam(name = "password", value = "密码", required = true, dataType = "string"),
    })
    @PostMapping("/user/register/login/sms")
    public Result registerLogin(@RequestParam("phone") String phone, /*@RequestParam("sms") String sms,*/
                        @RequestParam("password") String password,
                        HttpServletResponse response) {
    /*    //1.验证手机号码是否正确
        if (!checkPhone(phone)) {
            return ResultUtils.returnFail("手机号码错误，请重新输入", "200001");
        }

        //2.校验验证码是否存在在redis中
        String key = Constants.Redis.PREFIX_SMS + "1" + ":" + phone;
        String keyvalue = (String) redisUtil.get(key);
        if (keyvalue == null || !keyvalue.equals(sms)) {
            return ResultUtils.returnFail("验证码有误，请重新输入", "200004");
        }*/
        Map<String, Object> map = new HashMap<String, Object>();
        map.put("userPhone",phone);
        List<User> listUser = userService.getUserListByMap(map);
        if (listUser != null && listUser.size()>0) {
                return ResultUtils.returnFail("该手机已经注册");
        }
        //3.实现登录功能
        TokenVo tokenVo = null;
        try {
            User user = new User();
            user.setUserPhone(phone);
            user.setUserPassword(password);
            user.setUserRole(0);
            userService.qdtxAddUser(user);
            //4.生成系统令牌
            tokenVo = tokenService.genenrateToken(user);

            //5.保存到Redis中
            tokenService.saveToken(tokenVo.getToken(), user);
        } catch (Exception e) {
            e.printStackTrace();
            return ResultUtils.returnFail("数据库异常,注册失败", "200005");
        }
        response.setHeader("token", tokenVo.getToken());
        return ResultUtils.returnDataSuccess(tokenVo);
    }

    @ApiOperation(value = "手机验证码登录接口", produces = "application/json", notes = "使用手机验证码进行注册、登录接口")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "phone", value = "手机号码", required = true, dataType = "string"),
            @ApiImplicitParam(name = "sms", value = "验证码", required = true, dataType = "string"),
            @ApiImplicitParam(name = "userWeChatOpenId", value = "OPenid", required = false, dataType = "string")
    })
    @PostMapping("/user/login/sms")
    public Result login(@RequestParam("phone") String phone, @RequestParam("sms") String sms,
                        @RequestParam(required = false) String userWeChatOpenId,
                        HttpServletResponse response) {
        //1.验证手机号码是否正确
        if (!checkPhone(phone)) {
            return ResultUtils.returnFail("手机号码错误，请重新输入", "200001");
        }

        //2.校验验证码是否存在在redis中
        String key = Constants.Redis.PREFIX_SMS + "0" + ":" + phone;
        String keyvalue = (String) redisUtil.get(key);
        if (keyvalue == null || !keyvalue.equals(sms)) {
            return ResultUtils.returnFail("验证码有误，请重新输入", "200004");
        }
        Map<String, Object> map = new HashMap<String, Object>();
        map.put("userPhone", phone);
        List<User> listUser = userService.getUserListByMap(map);
        if (listUser != null) {
            User user = listUser.get(0);
            if (user.getBlacklist() == 1) {
                return ResultUtils.returnFail("当前账号被拉黑无法登录");
            }
        }
        //3.实现登录功能
        TokenVo tokenVo = null;
        try {
            User user = null;
            if (userWeChatOpenId == null) {
                user = userService.getUserByPhone(phone);
            } else {
                Map<String, Object> map1 = new HashMap<String, Object>();
                map1.put("userWeChatOpenId", userWeChatOpenId);
                List<User> listUser1 = userService.getUserListByMap(map);
                int id = 0;
                for (User list : listUser1) {
                    id = list.getId();
                }
                User user1 = new User();
                user1.setId(id);
                user1.setUserWeChatOpenId(phone);
                int i = userService.qdtxModifyUser(user1);
                if (i != 0) {
                    user = userService.getUserByPhoneOpenid(phone, userWeChatOpenId);
                } else {
                    return ResultUtils.returnFail("数据库异常,插入数据失败", "200006");
                }
            }
            //查询全部redis
            Set adminTokens = getRedis();
            for(Object adminToken :adminTokens){
                String token = adminToken.toString().substring(adminToken.toString().indexOf("-")+22,adminToken.toString().length());
                if(token.equals(phone)){
                    redisUtil.del(adminToken.toString());
                }
            }
            //4.生成系统令牌
            tokenVo = tokenService.genenrateToken(user);
            //5.保存到Redis中
            tokenService.saveToken(tokenVo.getToken(), user);
        } catch (EstSQLException e) {
            e.printStackTrace();
            return ResultUtils.returnFail("数据库异常,请再次登陆", "200005");
        }
        response.setHeader("token", tokenVo.getToken());
        return ResultUtils.returnDataSuccess(tokenVo);
    }


    //判断手机号码
    private boolean checkPhone(String phone) {
        boolean flag = false;
        if (!StringUtils.isBlank(phone)) {
            //正则表达式
            flag = phone.matches(Constants.PHONE_REGSTR);
        }
        return flag;
    }

    //判断验证码类型
    private boolean checkCodeType(String codeType) {
        boolean flag = false;
        if (codeType != null) {
            if (codeType.equals("0") || codeType.equals("1") || codeType.equals("2"))
                flag = true;
        }
        return flag;
    }

    //4.把验证码放在redis中、
    private boolean checksmsCode(String phone, Integer codeType) {
        String key = Constants.Redis.PREFIX_SMS + codeType + ":" + phone;
        //4.把验证码放在redis中、
        String code = (String) redisUtil.get(key);
        if (code != null) {
            return false;
        }
        return true;
    }

    @ApiOperation(value = "管理员获取个人信息", produces = "application/json", notes = "通过Token获取管理员个人信息")
    @GetMapping("/admin/token")
    public Result adminToken(HttpServletRequest request){
        String token=request.getHeader("token");
        User user = (User) redisUtil.get(token);
        return ResultUtils.returnDataSuccess(user);
    }

    @ApiOperation(value = " 账号密码登录", produces = "application/json", notes = "使用账号密码登录")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "account", value = "账号", required = true, dataType = "string"),
            @ApiImplicitParam(name = "password", value = "密码", required = true, dataType = "string"),
            @ApiImplicitParam(name = "logintype", value = "0：管理员，1：医院，2：医生，3：普通用户", required = true, dataType = "string")
    })
    @PostMapping("/user/login/password")
    public Result loginPassword(@RequestParam("account") String account, @RequestParam("password") String password,
                                @RequestParam("logintype") String logintype,HttpServletResponse response,HttpServletRequest request) {
        if (logintype.equals("0")) {
            Map<String, Object> map = new HashMap<String, Object>();
            map.put("accountId", account);
            List<User> listUser = userService.getUserListByMap(map);
            //判断User表 是否有该账号
            if (listUser != null && listUser.size() > 0) {
                User user = listUser.get(0);
                //判断该账号的密码是否正确，判断user角色是否是管理员
                if (user.getUserPassword().equals(password) && user.getUserRole() == 1) {
                    TokenVo tokenVo = null;
                    String phone=user.getUserPhone();
                    Set adminTokens = getRedis();
                    for(Object adminToken :adminTokens){
                        String token = adminToken.toString().substring(adminToken.toString().indexOf("-")+22,adminToken.toString().length());
                        if(token.equals(phone)){
                            redisUtil.del(adminToken.toString());
                        }
                    }
                    tokenVo = tokenService.genenrateToken(user);
                    tokenService.saveToken(tokenVo.getToken(),user);
                    response.setHeader("Access-Control-Expose-Headers","Cache-Control,Content-Type,Expires,Pragma,Content-Language,Last-Modified,token");
                    response.setHeader("token",tokenVo.getToken()); //设置响应头
                    return ResultUtils.returnSuccess("超级管理员登录成功", 4001);
                }
                return ResultUtils.returnFail("账号密码不存在");
            }
        } else if(logintype.equals("3")) {
            Map<String, Object> map = new HashMap<String, Object>();
            map.put("userPhone", account);
            List<User> listUser = userService.getUserListByMap(map);
            //判断User表 是否有该账号
            if (listUser != null && listUser.size() > 0) {
                User user = listUser.get(0);
                //判断该账号的密码是否正确，判断user角色是否是普通用户
                if (user.getUserPassword().equals(password) && user.getUserRole() == 0) {
                    if(user.getBlacklist() == 1){
                        return ResultUtils.returnFail("该用户账号被禁用，请联系管理员");
                    }
                    TokenVo tokenVo = null;
                    String phone=user.getUserPhone();
                    Set adminTokens = getRedis();
                    for(Object adminToken :adminTokens){
                        String token = adminToken.toString().substring(adminToken.toString().indexOf("-")+22,adminToken.toString().length());
                        if(token.equals(phone)){
                            redisUtil.del(adminToken.toString());
                        }
                    }
                    tokenVo = tokenService.genenrateToken(user);
                    tokenService.saveToken(tokenVo.getToken(),user);
                    response.setHeader("Access-Control-Expose-Headers","Cache-Control,Content-Type,Expires,Pragma,Content-Language,Last-Modified,token");
                    response.setHeader("token",tokenVo.getToken()); //设置响应头
                    return ResultUtils.returnSuccess("登录成功", 4004);
                }
                return ResultUtils.returnFail("账号密码不存在");
            }
        } else if (logintype.equals("1")) {
            Map<String, Object> map = new HashMap<String, Object>();
            map.put("account", account);
            List<Hospital> listHospital = HospitalService.getHospitalListByMap(map);
            //判断Hospital 是否有该账号
            if (listHospital != null && listHospital.size() > 0) {
                Hospital hospital = listHospital.get(0);
                //判断该账号的密码是否正确
                if (hospital.getPassword().equals(password)) {
                    TokenVo tokenVo = null;
                    String phone=hospital.getHospitalphone();
                    Set hospitalTokens = getRedis();
                    for(Object hospitalToken :hospitalTokens){
                        String token = hospitalToken.toString().substring(hospitalToken.toString().indexOf("-")+22,hospitalToken.toString().length());
                        if(token.equals(phone)){
                            redisUtil.del(hospitalToken.toString());
                        }
                    }
                    tokenVo = tokenService.genenrateToken(hospital);
                    tokenService.saveToken(tokenVo.getToken(), hospital);
                    response.setHeader("token", tokenVo.getToken());
                    return ResultUtils.returnSuccess("医院登录成功", 4002);
                }
            }
        } else if (logintype.equals("2")) {
            Map<String, Object> map = new HashMap<String, Object>();
            map.put("account", account);
            List<Doctor> listDoctor = doctorService.getDoctorListByMap(map);
            //判断HDoctor 是否有该账号
            if (listDoctor != null && listDoctor.size() > 0) {
                Doctor doctor = listDoctor.get(0);
                if (doctor.getPassword().equals(password)) {
                    //获取该账号医生ID
                    int doctorId = doctor.getDoctorId();
                    Map<String, Object> map1 = new HashMap<String, Object>();
                    map1.put("doctorId", doctorId);
                    List<HdidRelation> listHdidRelation = hdidRelationService.getHdidRelationListByMap(map1);
                    //查看listHdidRelation表内 是否有该医生
                    if (listHdidRelation != null && listHdidRelation.size() > 0) {
                        HdidRelation hdidRelation = listHdidRelation.get(0);
                        //查看listHdidRelation表内 该医生是否被禁用
                        if (hdidRelation.getForbidden() == 0) {
                            TokenVo tokenVo = null;
                            String phone=doctor.getPhone();
                            Set doctorTokens = getRedis();
                            for(Object doctorToken :doctorTokens){
                                String token = doctorToken.toString().substring(doctorToken.toString().indexOf("-")+22,doctorToken.toString().length());
                                if(token.equals(phone)){
                                    redisUtil.del(doctorToken.toString());
                                }
                            }
                            tokenVo = tokenService.genenrateToken(doctor);
                            tokenService.saveToken(tokenVo.getToken(), doctor);
                            response.setHeader("token", tokenVo.getToken());
                            return ResultUtils.returnSuccess("医生登录成功", 4003);
                        } else {
                            return ResultUtils.returnFail("该医生账号被禁用");
                        }
                    }
                }
            }
        }
        return ResultUtils.returnFail("账号密码错误");
    }

    @ApiOperation(value = "退出账号")
    @PostMapping("/user/exit/token")
    public Result exitToken(HttpServletRequest request){
       String token =request.getHeader("token");
        redisUtil.del(token);
        return ResultUtils.returnSuccess("退出成功");
    }
}
